﻿using BaseTool;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace StructuredLightSystemUI
{
    /// <summary>
    /// 相机测试页面
    /// </summary>
    public partial class ConCamera : UserControl
    {
        /// <summary> 相机工具 </summary>
        private CameraTool tool { get { return MyGlobal.CameraTool; } }

        /// <summary> 观察线程信号 </summary>
        private ManualResetEvent ThreadObserveEvent = new ManualResetEvent(false);
        /// <summary> 正在刷新控件 </summary>
        private bool isRefreshControl = false;
        /// <summary> 软触发采集一次 </summary>
        private bool isCaptureTriggerOnce = false;
        /// <summary> 锁：观察 </summary>
        private readonly object lockObserve = new object();
        /// <summary> 最后连接状态 </summary>
        private bool isLastStatus = false;


        #region 构造、初始化
        /// <summary>
        /// 构造
        /// </summary>
        public ConCamera()
        {
            InitializeComponent();
        }

        //加载时
        private void ConCamera_Load(object sender, EventArgs e)
        {
            Machine.ChangeProductAction += RefreshControl;

            Thread thread = new Thread(ThreadObserve);
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary> 打开用户控件 </summary>
        public void OpenControl()
        {
            RefreshControl();
            timer1.Enabled = true;
        }

        /// <summary> 关闭用户控件 </summary>
        public void CloseControl()
        {
            timer1.Enabled = false;
            Observe(0);
        }

        #endregion

        /// <summary>
        /// 刷新窗体信息
        /// </summary>
        private void RefreshControl()
        {
            isRefreshControl = true;

            try
            {
                bool isCon = tool.IsConnected;
                bool isGra = tool.IsGrabbing;
                //刷新下拉框事件
                if (!isCon)
                {
                    string[] dList = tool.RefreshDeviceList();
                    if (cb_CameraSelect.Items.Count != dList.Length)
                    {
                        cb_CameraSelect.Items.Clear();
                        cb_CameraSelect.Items.AddRange(dList);
                        cb_CameraSelect.Text = tool.Param.Name;
                    }
                }

                cb_CameraSelect.Enabled = !isCon;
                b_Open.Text = isCon ? "关闭相机" : "打开相机";

                gb_capture.Enabled = isCon;
                gb_param.Enabled = isCon;
                gb_focus.Enabled = isCon;

                //刷新相机可设置参数
                CameraHardwareParam set = tool.Param.Write;
                if (cb_ImagePixelFormat.Items == null || cb_ImagePixelFormat.Items.Count == 0)
                    cb_ImagePixelFormat.Items.AddRange(set.GetSupportPixelFormats);
                if (cb_TriggerSource.Items == null || cb_TriggerSource.Items.Count == 0)
                    cb_TriggerSource.Items.AddRange(set.GetSupportTriggerSource);
                if (isCon)
                {
                    cb_ParamEnable.Checked = set.ParamEnable;
                    cb_ImagePixelFormat.Text = set.PixelFormat;
                    nud_Exposure.Value = (decimal)set.ExposureTime;
                    nud_Gain.Value = 
                        (decimal)set.Gain < nud_Gain.Minimum ? nud_Gain.Minimum :
                        ((decimal)set.Gain > nud_Gain.Maximum ? nud_Gain.Maximum : (decimal)set.Gain);
                    cb_TriggerSource.Text = set.TriggerSource;

                    bool isEnable = set.ParamEnable /*&& !isGra*/;
                    //cb_ParamEnable.Enabled = !isGra;
                    cb_ImagePixelFormat.Enabled = isEnable;
                    nud_Exposure.Enabled = isEnable;
                    nud_Gain.Enabled = isEnable;
                    cb_TriggerSource.Enabled = isEnable;
                }

                //刷新读取参数
                if (isCon)
                {
                    if (!isGra)
                        tool.GetParam();

                    CameraHardwareParam read = tool.Param.Read;
                    l_ImagePixelFormat.Text = read.PixelFormat;
                    l_Exposure.Text = read.ExposureTime.ToString() + "us";
                    l_Gain.Text = read.Gain.ToString() + "dB";
                    l_TriggerSource.Text = read.TriggerSource;
                }
                else
                {
                    l_ImagePixelFormat.Text = "";
                    l_Exposure.Text = "";
                    l_Gain.Text = "";
                    l_TriggerSource.Text = "";
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
            finally
            {
                isLastStatus = tool.IsConnected;
                isRefreshControl = false;
            }
        }

        #region 初始化
        //下拉框刷新
        private void cb_CameraSelect_DropDown(object sender, EventArgs e)
        {
            RefreshControl();
        }
        //下拉框选择
        private void cb_CameraSelect_TextChanged(object sender, EventArgs e)
        {
            if (isRefreshControl)
                return;
            try
            {
                tool.Param.Name = cb_CameraSelect.Text;
                tool.Save();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //打开关闭相机
        private void b_Open_Click(object sender, EventArgs e)
        {
            try
            {
                if (tool.IsConnected)
                {
                    if (tool.IsGrabbing)
                        tool.StopGrab();
                    Log.SaveLog($"关闭相机中", LogType.Run, Color.Black);
                    tool.CloseCamera();
                }
                else
                {
                    Log.SaveLog($"打开相机中", LogType.Run, Color.Black);
                    tool.ConnectedCamera();
                }
                RefreshControl();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex, $"打开/关闭相机异常，{ex.Message}", LogType.Run);
            }
        }
        #endregion

        #region 采集设置
        //观察（视频流）
        private void b_Observe1_Click(object sender, EventArgs e)
        {
            Observe(1);
        }
        //观察（软触发）
        private void b_Observe2_Click(object sender, EventArgs e)
        {
            Observe(2);
        }
        //观察（硬触发）
        private void b_Observe3_Click(object sender, EventArgs e)
        {
            Observe(3);
        }
        //软触发一次
        private void b_Observe4_Click(object sender, EventArgs e)
        {
            Observe(4);
        }
        //停止观察
        private void b_StopObserve_Click(object sender, EventArgs e)
        {
            Observe(0);
        }
        //打开文件夹
        private void b_OpenFolder_Click(object sender, EventArgs e)
        {
            FileTool.OpenFolder(PathTool.DataCapturePath, true);
        }
        /// <summary>
        /// 观察
        /// </summary>
        /// <param name="index"></param>
        private void Observe(int index)
        {
            if (!tool.IsConnected)
                return;
            lock (lockObserve)
            {
                //停止观察
                if (tool.IsGrabbing)
                {
                    ThreadObserveEvent.Reset();
                    tool.StopGrab();
                }

                switch (index)
                {
                    //停止观察
                    case 0:
                        {
                            RefreshObserve(false);
                            return;
                        }
                    //观察（视频流）
                    case 1:
                        {
                            tool.Capture = new CameraCapture();
                            tool.Capture.CaptureMode = CameraCaptureMode.连续采集指针模式;
                            tool.Capture.HandlePictureBox = conPictureBox1.Handle;

                            tool.SetParam(tool.Param.Write);
                            tool.SetContinuesMode();
                            tool.StartGrab();
                            break;
                        }
                    //观察（软触发）
                    case 2:
                        {
                            tool.Capture = new CameraCapture();
                            tool.Capture.CaptureMode = CameraCaptureMode.软触发采集异步模式;

                            tool.SetParam(tool.Param.Write);
                            tool.SetSoftTrigger();
                            tool.StartGrab();
                            ThreadObserveEvent.Set();
                            break;
                        }
                    //观察（硬触发）
                    case 3:
                        {
                            tool.Capture = new CameraCapture();
                            tool.Capture.CaptureMode = CameraCaptureMode.硬触发采集异步模式;

                            tool.SetParam(tool.Param.Write);
                            tool.SetHardTrigger(tool.Param.Write);
                            tool.StartGrab();
                            ThreadObserveEvent.Set();
                            break;
                        }
                    //软触发一次
                    case 4:
                        {
                            tool.Capture = new CameraCapture();
                            tool.Capture.CaptureMode = CameraCaptureMode.软触发采集异步模式;
                            isCaptureTriggerOnce = true;

                            tool.SetParam(tool.Param.Write);
                            tool.SetSoftTrigger();
                            tool.StartGrab();
                            ThreadObserveEvent.Set();
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 观察线程
        /// </summary>
        private void ThreadObserve()
        {
            while (!Machine.WillExit)
            {
                Thread.Sleep(1);
                if (!ThreadObserveEvent.WaitOne(1000))
                    continue;

                if (this.Parent == null)
                    continue;

                if (!tool.IsGrabbing)
                    continue;

                RefreshObserve(true);

                switch (tool.Capture.CaptureMode)
                {
                    case CameraCaptureMode.软触发采集异步模式:
                        {
                            tool.SynchronousSoftTrigger();
                            break;
                        }
                    case CameraCaptureMode.硬触发采集异步模式:
                        {
                            break;
                        }
                    default:
                        {
                            ThreadObserveEvent.Reset();
                            goto gotoContinue;
                        }
                }

                //取图
                Mat image;
                string msg = tool.SynchronousSoftTrigger(out image, tool.Param.OverTime);
                if (msg != "OK")
                {
                    Log.SaveLog(msg, LogType.Run, Color.Red);
                    goto gotoContinue;
                }

                //图片保存和显示
                ImageSaveAndShow(image);

                //对焦算法
                AC(image);

                //清空信号
                if (isCaptureTriggerOnce)
                {
                    isCaptureTriggerOnce = false;
                    ThreadObserveEvent.Reset();
                }

            gotoContinue:
                RefreshObserve(false);
            }
        }
        /// <summary>
        /// 图片保存和显示
        /// </summary>
        /// <param name="image"></param>
        private void ImageSaveAndShow(Mat image)
        {
            try
            {
                //显示
                conPictureBox1.ShowImage = image.ToBitmap();

                //保存
                if (cb_SaveImage.Checked)
                {
                    DateTime now = DateTime.Now;
                    FileInfo fi = new FileInfo($"{PathTool.DataCapturePath}{now.ToString("yyyy年MM月dd日")}\\{now.ToString("HHmmss_fffffff")}.jpg");

                    if (!fi.Directory.Exists)
                        fi.Directory.Create();

                    Cv2.ImWrite(fi.FullName, image);
                }
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        /// <summary>
        /// 刷新观察控件状态
        /// </summary>
        /// <param name="isObserve"></param>
        private void RefreshObserve(bool isObserve)
        {
            gb_capture.Invoke((MethodInvoker)delegate
            {
                b_Observe1.Enabled = !isObserve;
                b_Observe2.Enabled = !isObserve;
                b_Observe3.Enabled = !isObserve;
                b_Observe4.Enabled = !isObserve;
                b_StopObserve.Enabled = true;
            });
        }
        #endregion

        #region 参数设置
        //使能
        private void cb_ParamEnable_CheckedChanged(object sender, EventArgs e)
        {
            if (isRefreshControl)
                return;

            try
            {
                CameraHardwareParam set = tool.Param.Write;
                set.ParamEnable = cb_ParamEnable.Checked;
                tool.Save();
                tool.SetParam(set);

                RefreshControl();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //图像格式
        private void cb_ImagePixelFormat_TextChanged(object sender, EventArgs e)
        {
            if (isRefreshControl)
                return;

            try
            {
                if (string.IsNullOrWhiteSpace(cb_ImagePixelFormat.Text))
                    return;

                CameraHardwareParam set = tool.Param.Write;
                set.PixelFormat = cb_ImagePixelFormat.Text;
                tool.Save();
                tool.SetParam(set);

                RefreshControl();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //曝光事件
        private void nud_Exposure_ValueChanged(object sender, EventArgs e)
        {
            if (isRefreshControl)
                return;

            try
            {
                CameraHardwareParam set = tool.Param.Write;
                set.ExposureTime = (float)nud_Exposure.Value;
                tool.Save();
                tool.SetParam(set);

                RefreshControl();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //增益
        private void nud_Gain_ValueChanged(object sender, EventArgs e)
        {
            if (isRefreshControl)
                return;

            try
            {
                CameraHardwareParam set = tool.Param.Write;
                set.Gain = (float)nud_Gain.Value;
                tool.Save();
                tool.SetParam(set);

                RefreshControl();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //硬触发源
        private void cb_TriggerSource_TextChanged(object sender, EventArgs e)
        {
            if (isRefreshControl)
                return;

            try
            {
                if (string.IsNullOrWhiteSpace(cb_TriggerSource.Text))
                    return;
                CameraHardwareParam set = tool.Param.Write;
                set.TriggerSource = cb_TriggerSource.Text;
                tool.Save();
                tool.SetParam(set);

                RefreshControl();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //保存至标定参数
        private void b_calibration_Click(object sender, EventArgs e)
        {
            try
            {
                tool.Param.Calibration = (CameraHardwareParam)FileTool.CloneClass(tool.Param.Write);
                tool.Save();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        //保存至重建参数
        private void b_reconstruct_Click(object sender, EventArgs e)
        {
            try
            {
                tool.Param.Reconstruct = (CameraHardwareParam)FileTool.CloneClass(tool.Param.Write);
                tool.Save();
            }
            catch (Exception ex)
            {
                Log.SaveError(ex);
            }
        }
        #endregion

        #region 自动对焦
        /// <summary> 对焦算法1：Tenegrad </summary>
        private List<double> ACTenegradList = new List<double>();
        /// <summary> 对焦算法2：Variance </summary>
        private List<double> ACVarianceList = new List<double>();
        /// <summary> 对焦算法1：Tenegrad </summary>
        private double ACTenegradMax = 0;
        /// <summary> 对焦算法2：Variance </summary>
        private double ACVarianceMax = 0;
        /// <summary> 标签框长度 </summary>
        private const int PadNum = 10;
        /// <summary> 运行锁 </summary>
        private readonly object lockChartAC1 = new object();
        /// <summary> 运行锁 </summary>
        private readonly object lockChartAC2 = new object();


        /// <summary>
        /// 对焦计算
        /// </summary>
        private void AC(Mat image)
        {
            tabControl1.Invoke((MethodInvoker)delegate
            {
                try
                {
                    if (tabControl1.SelectedIndex != 1)
                        return;

                    //AC_Tenegrad
                    double tenegrad = AC_Tenegrad(image);
                    if (tenegrad > ACTenegradMax) { ACTenegradMax = tenegrad; }
                    if (tenegrad != -1) ACTenegradList.Add(tenegrad);

                    l_AC1.Text =
                    "当前值：".PadRight(PadNum) + (tenegrad == -1 ? "异常\r\n" : tenegrad.ToString("f2") + "\r\n") +
                    "最大值：".PadRight(PadNum) + ACTenegradMax.ToString("f2");
                    RefreshChartAC1(tenegrad);


                    //AC_Variance
                    double variance = AC_Variance(image);
                    if (variance > ACVarianceMax) { ACVarianceMax = variance; }
                    if (variance != -1) ACVarianceList.Add(variance);

                    l_AC2.Text =
                        "当前值：".PadRight(PadNum) + (variance == -1 ? "异常\r\n" : variance.ToString("f2") + "\r\n") +
                        "最大值：".PadRight(PadNum) + ACVarianceMax.ToString("f2");
                    RefreshChartAC2(variance);
                }
                catch (Exception ex)
                {
                    Log.SaveError(ex);
                }
            });
        }

        /// <summary>
        /// 自动对焦算法（Tenegrad）
        /// </summary>
        /// <param name="gray"></param>
        /// <returns></returns>
        private double AC_Tenegrad(Mat gray)
        {
            try
            {
                Mat xgrad = new Mat();
                Mat ygrad = new Mat();
                Cv2.Sobel(gray, xgrad, MatType.CV_32F, 1, 0);
                Cv2.Sobel(gray, ygrad, MatType.CV_32F, 0, 1);

                Mat Sxy = new Mat();
                Cv2.Sqrt((xgrad.Mul(xgrad) + ygrad.Mul(ygrad)), Sxy);
                Cv2.Pow(Sxy, 2, Sxy);
                double outvalue = Cv2.Mean(Sxy)[0];

                xgrad.Dispose();
                ygrad.Dispose();
                Sxy.Dispose();
                return outvalue;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex, $"计算自动对焦异常（Tenegrad），{ex.Message}", LogType.Run);
                return -1;
            }
        }
        /// <summary>
        /// 自动对焦算法（Variance）
        /// </summary>
        /// <param name="gray"></param>
        /// <returns></returns>
        private double AC_Variance(Mat gray)
        {
            try
            {
                Mat mean = new Mat();
                Mat std = new Mat();
                Cv2.MeanStdDev(gray, mean, std);
                double outvalue = std.At<double>(0, 0);

                mean.Dispose();
                std.Dispose();
                return outvalue;
            }
            catch (Exception ex)
            {
                Log.SaveError(ex, $"计算自动对焦异常（Variance），{ex.Message}", LogType.Run);
                return -1;
            }
        }

        /// <summary> 
        /// 清空对焦
        /// </summary>
        private void AC_Clear()
        {
            //ACCount = 0;

            ACTenegradList.Clear();
            ACTenegradMax = 0;
            l_AC1.Text = "当前值：".PadRight(PadNum) + "0\r\n" + "最大值：".PadRight(PadNum) + "0";

            ACVarianceList.Clear();
            ACVarianceMax = 0;
            l_AC2.Text = "当前值：".PadRight(PadNum) + "0\r\n" + "最大值：".PadRight(PadNum) + "0";

            RefreshChartAC1();
            RefreshChartAC2();
        }

        /// <summary>
        /// 刷新AC1
        /// </summary>
        /// <param name="tenegrad"></param>
        private void RefreshChartAC1(double tenegrad = 0)
        {
            if (tenegrad == -1) return;
            chartAC1.BeginInvoke((MethodInvoker)delegate
            {
                lock (lockChartAC1)
                {
                    chartAC1.Series[0].Points.Clear();
                    chartAC1.ChartAreas[0].AxisY.CustomLabels.Clear();

                    int count = Math.Min(ACTenegradList.Count, 100);
                    if (count <= 0) return;

                    //添加点数据
                    for (int index = ACTenegradList.Count - count; index < ACTenegradList.Count; index++)
                    {
                        chartAC1.Series[0].Points.Add(ACTenegradList[index]);
                    }

                    int XInterval = (int)Math.Ceiling((double)count / 10.0);
                    chartAC1.ChartAreas[0].AxisX.Interval = XInterval;

                    double pointsMax = ACTenegradList.Max();
                    double pointsMin = ACTenegradList.Min();
                    double length = pointsMax - pointsMin;
                    if (length <= 0) length = 1;

                    double Dif = length / 6.0;

                    chartAC1.ChartAreas[0].AxisY.Minimum = pointsMin - Dif;
                    chartAC1.ChartAreas[0].AxisY.Maximum = pointsMax + Dif;
                    chartAC1.ChartAreas[0].AxisY.IntervalAutoMode = IntervalAutoMode.FixedCount;
                    chartAC1.ChartAreas[0].AxisY.IsLabelAutoFit = false;
                    chartAC1.ChartAreas[0].AxisY.CustomLabels.Add(pointsMax - 0.1, pointsMax + 0.1, $"max ({pointsMax.ToString("f0")})");
                    chartAC1.ChartAreas[0].AxisY.CustomLabels.Add(pointsMin - 0.1, pointsMin + 0.1, $"min ({pointsMin.ToString("f0")})");

                    double TopToDown = Dif * 8;

                    chartAC1.ChartAreas[0].AxisY.MajorGrid.Enabled = true;
                    chartAC1.ChartAreas[0].AxisY.MajorTickMark.Enabled = true;
                    chartAC1.ChartAreas[0].AxisY.MajorGrid.IntervalOffset = Dif;
                    chartAC1.ChartAreas[0].AxisY.MajorGrid.Interval = length;
                    chartAC1.ChartAreas[0].AxisY.MajorTickMark.IntervalOffset = Dif;
                    chartAC1.ChartAreas[0].AxisY.MajorTickMark.Interval = length;
                    chartAC1.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Solid;

                    chartAC1.ChartAreas[0].AxisY.MinorGrid.Enabled = true;
                    chartAC1.ChartAreas[0].AxisY.MinorTickMark.Enabled = true;
                    chartAC1.ChartAreas[0].AxisY.MinorGrid.IntervalOffset = tenegrad - (pointsMin - Dif);
                    chartAC1.ChartAreas[0].AxisY.MinorGrid.Interval = TopToDown;
                    chartAC1.ChartAreas[0].AxisY.MinorTickMark.IntervalOffset = tenegrad - (pointsMin - Dif);
                    chartAC1.ChartAreas[0].AxisY.MinorTickMark.Interval = TopToDown;
                    chartAC1.ChartAreas[0].AxisY.MinorGrid.LineDashStyle = ChartDashStyle.Dash;
                }
            });
        }
        /// <summary>
        /// 刷新AC2
        /// </summary>
        /// <param name="variance"></param>
        private void RefreshChartAC2(double variance = 0)
        {
            if (variance == -1) return;
            chartAC2.BeginInvoke((MethodInvoker)delegate
            {
                lock (lockChartAC2)
                {
                    chartAC2.Series[0].Points.Clear();
                    chartAC2.ChartAreas[0].AxisY.CustomLabels.Clear();

                    int count = Math.Min(ACVarianceList.Count, 100);
                    if (count <= 0) return;

                    //添加点数据
                    for (int index = ACVarianceList.Count - count; index < ACVarianceList.Count; index++)
                    {
                        chartAC2.Series[0].Points.Add(ACVarianceList[index]);
                    }

                    int XInterval = (int)Math.Ceiling((double)count / 10.0);
                    chartAC2.ChartAreas[0].AxisX.Interval = XInterval;

                    double pointsMax = ACVarianceList.Max();
                    double pointsMin = ACVarianceList.Min();
                    double length = pointsMax - pointsMin;
                    if (length <= 0) length = 1;

                    double Dif = length / 6.0;

                    chartAC2.ChartAreas[0].AxisY.Minimum = pointsMin - Dif;
                    chartAC2.ChartAreas[0].AxisY.Maximum = pointsMax + Dif;
                    chartAC2.ChartAreas[0].AxisY.IntervalAutoMode = IntervalAutoMode.FixedCount;
                    chartAC2.ChartAreas[0].AxisY.IsLabelAutoFit = false;
                    chartAC2.ChartAreas[0].AxisY.CustomLabels.Add(pointsMax - 0.1, pointsMax + 0.1, $"max ({pointsMax.ToString("f0")})");
                    chartAC2.ChartAreas[0].AxisY.CustomLabels.Add(pointsMin - 0.1, pointsMin + 0.1, $"min ({pointsMin.ToString("f0")})");

                    double TopToDown = Dif * 8;

                    chartAC2.ChartAreas[0].AxisY.MajorGrid.Enabled = true;
                    chartAC2.ChartAreas[0].AxisY.MajorTickMark.Enabled = true;
                    chartAC2.ChartAreas[0].AxisY.MajorGrid.IntervalOffset = Dif;
                    chartAC2.ChartAreas[0].AxisY.MajorGrid.Interval = length;
                    chartAC2.ChartAreas[0].AxisY.MajorTickMark.IntervalOffset = Dif;
                    chartAC2.ChartAreas[0].AxisY.MajorTickMark.Interval = length;
                    chartAC2.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Solid;

                    chartAC2.ChartAreas[0].AxisY.MinorGrid.Enabled = true;
                    chartAC2.ChartAreas[0].AxisY.MinorTickMark.Enabled = true;
                    chartAC2.ChartAreas[0].AxisY.MinorGrid.IntervalOffset = variance - (pointsMin - Dif);
                    chartAC2.ChartAreas[0].AxisY.MinorGrid.Interval = TopToDown;
                    chartAC2.ChartAreas[0].AxisY.MinorTickMark.IntervalOffset = variance - (pointsMin - Dif);
                    chartAC2.ChartAreas[0].AxisY.MinorTickMark.Interval = TopToDown;
                    chartAC2.ChartAreas[0].AxisY.MinorGrid.LineDashStyle = ChartDashStyle.Dash;
                }
            });
        }

        //清空
        private void chartAC_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            AC_Clear();
        }
        //清空
        private void l_AC_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            AC_Clear();
        }
        #endregion

        #region 杂项
        //定时器
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (tool.IsConnected != isLastStatus)
                RefreshControl();
        }
        #endregion
    }
}
